#pragma once
#include <iostream>
#include <string>
#include <cstring>
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#elif __linux__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif 
namespace LoggerSpace
{
    class Sock
    {
    public:
        Sock()
        {
            // 创建套接字
            _sock = socket(AF_INET, SOCK_STREAM, 0);
            if (_sock == -1)
                throw(std::string("套接字创建失败!"));
        }
        ~Sock()
        {
#ifdef _WIN32
            closesocket(_sock);
#elif __linux__
            close(_sock);
#endif 
        }
        bool Setsockopt(int level = SOL_SOCKET, int optname = SO_REUSEADDR)
        {
            const char opt = 1;
            int n = setsockopt(_sock, level, optname, &opt, sizeof(opt));
            return n != -1;
        }
        // 绑定ip地址和端口号
        bool Bind(uint16_t port, const std::string &ip = "")
        {
            sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_addr.s_addr = (ip == "" ? INADDR_ANY : inet_addr(ip.c_str()));
            local.sin_port = htons(port);
            int n = bind(_sock, (sockaddr *)&local, sizeof(local));
            return n != -1;
        }
        bool Listen(int backlog = 32)
        {
            int n = listen(_sock, backlog);
            return n != -1;
        }
#ifdef _WIN32
        SOCKET Accept(uint16_t &port, std::string &ip)
        {
            sockaddr_in peer;
            int len = sizeof(peer);
            SOCKET sd = accept(_sock, (sockaddr *)&peer, &len);
            if (sd != -1)
            {
                port = ntohs(peer.sin_port);
                ip = inet_ntoa(peer.sin_addr);
            }
            return sd;
        }
#elif __linux__
        int Accept(uint16_t &port, std::string &ip)
        {
            sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sd = accept(_sock, (sockaddr *)&peer, &len);
            if (sd != -1)
            {
                port = ntohs(peer.sin_port);
                ip = inet_ntoa(peer.sin_addr);
            }
            return sd;
        }
#endif // _WIN32
        bool Connect(const uint16_t &port, const std::string &ip)
        {
            sockaddr_in Server;
            memset(&Server, 0, sizeof(Server));
            Server.sin_family = AF_INET;
            Server.sin_addr.s_addr = inet_addr(ip.c_str());
            Server.sin_port = htons(port);
            int n = connect(_sock, (sockaddr *)&Server, sizeof(Server));
            return n != -1;
        }
#ifdef _WIN32
        SOCKET GetSd() const
#elif __linux__
        int GetSd() const
#endif
        {
            return _sock;
        }

    private:
#ifdef _WIN32
        SOCKET _sock;
#elif __linux__
        int _sock;
#endif
    };
}